#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>


BOOL GetProcessList();
BOOL ListProcessModules(DWORD dwPID);
BOOL ListProcessThreads(DWORD dwOwnerPID);
BOOL PrintMemoryInfo(DWORD processID);
void printError(TCHAR* msg);

int main()
{
  GetProcessList();
  return 0;
}

BOOL GetProcessList()
{
  HANDLE hProcessSnap;
  PROCESSENTRY32 pe32;

  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

  if (hProcessSnap == INVALID_HANDLE_VALUE)
  {
    printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
    return(FALSE);
  }

  pe32.dwSize = sizeof( PROCESSENTRY32 );

  if (!Process32First(hProcessSnap, &pe32))
  {
    printError(TEXT("Process32First")); 
    CloseHandle(hProcessSnap);
    return(FALSE);
  }

  do
  {
    _tprintf( TEXT("\n\n=====================================================" ));
    _tprintf( TEXT("\nPROCESS NAME:  %s"), pe32.szExeFile );
    _tprintf( TEXT("\n-------------------------------------------------------\n" ));
	
	PrintMemoryInfo(pe32.th32ProcessID);
	ListProcessModules(pe32.th32ProcessID);
	
  } while(Process32Next(hProcessSnap, &pe32));

  CloseHandle(hProcessSnap);
  return(TRUE);
}


BOOL ListProcessModules(DWORD dwPID)
{
  HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
  MODULEENTRY32 me32;

  hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
  if(hModuleSnap == INVALID_HANDLE_VALUE)
  {
    printError(TEXT("CreateToolhelp32Snapshot (of modules)"));
    return(FALSE);
  }

  me32.dwSize = sizeof(MODULEENTRY32);

  if(!Module32First(hModuleSnap, &me32))
  {
    printError(TEXT("Module32First")); 
    CloseHandle(hModuleSnap);
    return(FALSE);
  }

  _tprintf(TEXT("\nModules:"),   me32.szModule);

  do
  {
    _tprintf(TEXT("\n\n     MODULE NAME:     %s"), me32.szModule);
    _tprintf(TEXT("\n     Executable     = %s"), me32.szExePath);
    
  } while(Module32Next(hModuleSnap, &me32));

  CloseHandle(hModuleSnap);
  return(TRUE);
}

BOOL PrintMemoryInfo(DWORD processID)
{
    HANDLE hProcess;
    PROCESS_MEMORY_COUNTERS pmc;

	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
                             PROCESS_VM_READ,
                               FALSE, processID );
    if (NULL == hProcess)
        return FALSE;

	_tprintf( TEXT("Memory usage:\n") );
    
	if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
    {
        _tprintf(TEXT("\tPeakWorkingSetSize: %d\n"), pmc.PeakWorkingSetSize);
        _tprintf(TEXT("\tWorkingSetSize: %d\n"), pmc.WorkingSetSize);
        
		
		_tprintf(TEXT("\tQuotaPeakPagedPoolUsage: %d\n"), pmc.QuotaPeakPagedPoolUsage);
        _tprintf(TEXT("\tQuotaPagedPoolUsage: %d\n"), pmc.QuotaPagedPoolUsage);
    }

    CloseHandle(hProcess);
	return TRUE;
}



void printError(TCHAR* msg)
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;

  eNum = GetLastError();
  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         sysMsg, 256, NULL);

  p = sysMsg;
  while (( *p > 31 ) || ( *p == 9 ))
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );

  _tprintf(TEXT("\n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg);
}